package com.hifar.test.syncData.service.impl;


import com.alibaba.fastjson.JSON;
import com.hifar.base.serialNo.service.IBaseSerialNoService;
import com.hifar.fw.utils.lang.StringUtils;
import com.hifar.plat.baseModal.pojo.BaseOssFiles;
import com.hifar.plat.baseModal.service.IBaseOssFilesService;
import com.hifar.test.syncData.constant.SyncDataConstant;
import com.hifar.test.syncData.enums.SyncDataStatusEnum;
import com.hifar.test.syncData.pojo.HfEnvSyncDataExportTask;
import com.hifar.test.syncData.pojo.HfEnvSyncDataImportTask;
import com.hifar.test.syncData.pojo.HfEnvSyncTableConfig;
import com.hifar.test.syncData.pojo.model.EnvSyncDataAuthModel;
import com.hifar.test.syncData.service.IHfEnvSyncDataExportTaskService;
import com.hifar.test.syncData.service.IHfEnvSyncDataImportTaskService;
import com.hifar.test.syncData.service.IHfEnvSyncTableConfigService;
import com.hifar.test.syncData.service.ISyncDataService;
import com.hifar.utils.FileUtil;
import com.hifar.utils.ToolKit;
import com.tssk.kylx.fw.utils.id.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author zhuWeiWei
 * @description 同步数据
 * @date 2025/4/11 10:11
 */
@Service
@Slf4j
public class SyncDataServiceImpl implements ISyncDataService {

    @Autowired
    private IHfEnvSyncTableConfigService syncTableConfigService;
    @Autowired
    private IHfEnvSyncDataExportTaskService syncDataExportTaskService;
    @Autowired
    private IHfEnvSyncDataImportTaskService syncDataImportTaskService;

    @Autowired
    private IBaseOssFilesService baseOssFilesService;
    @Autowired
    private IBaseSerialNoService baseSerialNoService;

    @Override
    @Async
    public void exportData() {
        String taskId = null;
        try {
            // 第一步：查询同步表配置
            List<HfEnvSyncTableConfig> hfEnvSyncTableConfigs = syncTableConfigService.listSyncTable();
            
            // 空指针检查
            if (hfEnvSyncTableConfigs == null || hfEnvSyncTableConfigs.isEmpty()) {
                log.warn("没有配置需要同步的表，导出终止");
                return;
            }
            
            log.info("开始数据导出，共{}个表需要同步", hfEnvSyncTableConfigs.size());

            // 第二步：创建导出任务
            HfEnvSyncDataExportTask hfEnvSyncDataExportTask = new HfEnvSyncDataExportTask();
            hfEnvSyncDataExportTask.setStartTime(new Date());
            hfEnvSyncDataExportTask.setSchedule(BigDecimal.ZERO);
            hfEnvSyncDataExportTask.setStatus(SyncDataStatusEnum.UN_START.getValue());
            String syncCode = baseSerialNoService.getMouthSerialNo(SyncDataConstant.CODE_TYPE, "yyyyMMddHHmm", "SY", "", 2);
            hfEnvSyncDataExportTask.setSyncCode(syncCode);
            String tempPath = FileUtil.getTempPath();
            String baseTempPath = tempPath + File.separator + IdUtils.uuid32();
            File baseTempFile = new File(baseTempPath);
            if (!baseTempFile.exists()) {
                baseTempFile.mkdirs();
            }
            hfEnvSyncDataExportTask.setTempPath(baseTempPath);
            // 任务数量
            int taskCount = hfEnvSyncTableConfigs.size();
            hfEnvSyncDataExportTask.setTaskCount(taskCount);
            syncDataExportTaskService.save(hfEnvSyncDataExportTask);
            taskId = hfEnvSyncDataExportTask.getId();
            
            log.info("导出任务创建成功，任务ID：{}，同步编码：{}，临时目录：{}", taskId, syncCode, baseTempPath);

            // 第三步：循环导出各表数据
            log.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓");
            log.info("┃          开始批量导出表数据                    ┃");
            log.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
            
            int successCount = 0;
            int failCount = 0;
            long startTime = System.currentTimeMillis();
            
            for (int i = 0; i < hfEnvSyncTableConfigs.size(); i++) {
                HfEnvSyncTableConfig hfEnvSyncTableConfig = hfEnvSyncTableConfigs.get(i);
                String tableName = hfEnvSyncTableConfig != null ? hfEnvSyncTableConfig.getTableName() : "未知表";
                String description = hfEnvSyncTableConfig != null ? hfEnvSyncTableConfig.getDescription() : "";
                
                log.info("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                log.info("【进度】{}/{} - 当前表：{}（{}）", i + 1, taskCount, tableName, description);
                
                long tableStartTime = System.currentTimeMillis();
                try {
                    syncDataExportTaskService.syncTableData(taskId, hfEnvSyncTableConfig);
                    long tableEndTime = System.currentTimeMillis();
                    long tableDuration = (tableEndTime - tableStartTime) / 1000;
                    
                    BigDecimal schedule = calculateProgress(i + 1, taskCount);
                    syncDataExportTaskService.updateSchedule(taskId, schedule, SyncDataStatusEnum.RUN.getValue());
                    successCount++;
                    
                    log.info("【成功】表【{}】导出成功，耗时：{}秒，进度：{}%（{}/{}）", 
                            tableName, tableDuration, schedule, i + 1, taskCount);
                } catch (Exception e) {
                    long tableEndTime = System.currentTimeMillis();
                    long tableDuration = (tableEndTime - tableStartTime) / 1000;
                    failCount++;
                    
                    log.error("【失败】表【{}】导出失败，耗时：{}秒，任务ID：{}，错误：{}", 
                            tableName, tableDuration, taskId, e.getMessage(), e);
                    
                    // 单个表失败不影响整体流程，继续执行
                    try {
                        BigDecimal schedule = calculateProgress(i + 1, taskCount);
                        syncDataExportTaskService.updateSchedule(taskId, schedule, SyncDataStatusEnum.RUN.getValue());
                    } catch (Exception updateEx) {
                        log.error("更新进度失败：{}", updateEx.getMessage());
                    }
                }
            }
            
            long endTime = System.currentTimeMillis();
            long totalDuration = (endTime - startTime) / 1000;
            
            log.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓");
            log.info("┃          表数据导出汇总                        ┃");
            log.info("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫");
            log.info("┃  总表数：{} 个", String.format("%-36s", taskCount) + "┃");
            log.info("┃  成功：{} 个", String.format("%-38s", successCount) + "┃");
            log.info("┃  失败：{} 个", String.format("%-38s", failCount) + "┃");
            log.info("┃  总耗时：{} 秒", String.format("%-36s", totalDuration) + "┃");
            log.info("┃  平均耗时：{} 秒/表", String.format("%-32s", taskCount > 0 ? totalDuration / taskCount : 0) + "┃");
            log.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
            
            // 第四步：打包压缩上传
            syncDataExportTaskService.syncFile(taskId);
            
        } catch (Exception e) {
            log.error("数据导出异常，任务ID：{}，错误：{}", taskId, e.getMessage(), e);
            if (taskId != null) {
                syncDataExportTaskService.taskError(taskId, "导出异常: " + e.getMessage());
            }
        }
    }

    @Override
//    @Async
    public void importData(String fileId) {
        BaseOssFiles baseOssFiles = baseOssFilesService.getById(fileId);

        HfEnvSyncDataImportTask hfEnvSyncDataImportTask = new HfEnvSyncDataImportTask();
        hfEnvSyncDataImportTask.setStartTime(new Date());
        hfEnvSyncDataImportTask.setSchedule(BigDecimal.ZERO);
        hfEnvSyncDataImportTask.setStatus(SyncDataStatusEnum.UN_START.getValue());
        if (Objects.nonNull(baseOssFiles)) {
            hfEnvSyncDataImportTask.setFilePath(baseOssFiles.getFilePath());
            hfEnvSyncDataImportTask.setBucketPre(baseOssFiles.getBucketPre());
        }
        syncDataImportTaskService.save(hfEnvSyncDataImportTask);
        String taskId = hfEnvSyncDataImportTask.getId();
        if (Objects.isNull(baseOssFiles)) {
            syncDataImportTaskService.taskError(taskId, "文件不存在!");
            return;
        }
        Thread thread = new Thread(() -> {
            try {
                File file = syncDataImportTaskService.extractSyncImportFile(hfEnvSyncDataImportTask);
                if (Objects.isNull(file)) {
                    syncDataImportTaskService.taskError(taskId, "下载失败!");
                    return;
                }

                // 验证认证文件是否存在
                String authFilePath = file.getAbsolutePath() + File.separator + SyncDataConstant.AUTH_FILE_NAME;
                File authFile = new File(authFilePath);
                if (!authFile.exists()) {
                    syncDataImportTaskService.taskError(taskId, "导入认证文件不存在!");
                    return;
                }

                // 读取并解析认证文件
                String authText = ToolKit.readFile(authFile);
                if (StringUtils.isBlank(authText)) {
                    syncDataImportTaskService.taskError(taskId, "导入认证文件内容为空!");
                    return;
                }

                EnvSyncDataAuthModel envSyncDataAuthModel = null;
                try {
                    envSyncDataAuthModel = JSON.parseObject(authText, EnvSyncDataAuthModel.class);
                } catch (Exception e) {
                    log.error("解析认证文件失败，taskId: {}", taskId, e);
                    syncDataImportTaskService.taskError(taskId, "导入认证文件格式不正确: " + e.getMessage());
                    return;
                }

                if (Objects.isNull(envSyncDataAuthModel) || StringUtils.isBlank(envSyncDataAuthModel.getSyncCode())) {
                    syncDataImportTaskService.taskError(taskId, "导入认证文件数据不正确!");
                    return;
                }

                // 更新同步编码
                String syncCode = envSyncDataAuthModel.getSyncCode();
                syncDataImportTaskService.lambdaUpdate()
                    .set(HfEnvSyncDataImportTask::getSyncCode, syncCode)
                    .eq(HfEnvSyncDataImportTask::getId, taskId)
                    .update();

                // 导入数据信息
                syncDataImportTaskService.importDbData(taskId, file);

            } catch (Exception e) {
                log.error("导入数据异常，taskId: {}", taskId, e);
                syncDataImportTaskService.taskError(taskId, "导入失败: " + e.getMessage());
            }
        });

        // 设置线程名称，便于排查问题
        thread.setName("sync-import-task-" + taskId);

        // 设置未捕获异常处理器，防止线程静默终止
        thread.setUncaughtExceptionHandler((t, e) -> {
            log.error("导入线程异常终止: {}", t.getName(), e);
            syncDataImportTaskService.taskError(taskId, "系统异常: " + e.getMessage());
        });

        thread.start();
    }

    private BigDecimal calculateProgress(int progress, int taskCount) {
        return new BigDecimal(progress).multiply(new BigDecimal("90"))
                .divide(new BigDecimal(taskCount), 2, RoundingMode.HALF_UP);
    }

}
